#include "../include/Interpreter.h"
#include <string>
#include <iostream>

ofstream fa2;//输出结果 NOLINT
int cx;
vector<Interpreter> code;//存放虚拟机代码的容器

string fctToStr(fct f) {
    return fctMap.at(f);
}

void Interpreter::interpret() {
    fa2.open("fa2.txt");
    int ip;//instruction pointer指令指针
    int bp;//base pointer指令基址
    int sp;//stack pointer栈顶指针
    Interpreter i{};//存放当前指令
    vector<int> stack;//栈
    cout << "------start c0------" << endl;
    ip = bp = sp = 0;
    do {
        i = code[ip];//读取当前指令
        ip++;
        switch (i.f) {
            case LIT://将a的值取到栈顶
                stack.resize(sp + 1);
                stack[sp] = i.a;
                sp++;
                break;
            case LOD://将变量值取到栈顶，a为相对地址，l为层数
                stack.resize(sp + 1);
                stack[sp] = stack[base(i.l, stack, bp) + i.a];
                sp++;
                break;
            case STO://将栈顶内容送入某变量单元中，a为相对地址，l为层数
                stack.resize(sp);
                sp--;
                stack[base(i.l, stack, bp) + i.a] = stack[sp];
                break;
            case CAL://调动地址为a的过程，不可嵌套
                stack.resize(sp + 2);
                stack[sp] = bp;
                stack[sp + 1] = ip;
                bp = sp;
                ip = i.a;
                break;
            case INT://在运行栈中为被调用的过程开辟a个单元的数据区
                sp += i.a;
                stack.resize(sp);
                break;
            case JMP://无条件转移至地址a
                ip = i.a;
                break;
            case JPC://若栈顶为0，则转移至地址a
                sp--;
                if (stack[sp] == 0) {
                    ip = i.a;
                }
                break;
            case ADD://此栈顶与栈顶相加，结果存入次栈顶
                sp--;
                stack[sp - 1] = stack[sp - 1] + stack[sp];
                break;
            case SUB://此栈顶与栈顶相减，结果存入次栈顶
                sp--;
                stack[sp - 1] = stack[sp - 1] - stack[sp];
                break;
            case MUL://此栈顶与栈顶相乘，结果存入次栈顶
                sp--;
                stack[sp - 1] = stack[sp - 1] * stack[sp];
                break;
            case DIV://此栈顶与栈顶相除，结果存入次栈顶
                sp--;
                stack[sp - 1] = stack[sp - 1] / stack[sp];
                break;
            case RED://从命令行读入一个输入置于栈顶
                stack.resize(sp + 1);
                cout << "?";
                fa2 << "?";
                cin >> stack[sp];
                fa2 << stack[sp] << endl;
                sp++;
                break;
            case WRT://栈顶的值输出至控制台并换行
                cout << stack[sp - 1] << endl;
                fa2 << stack[sp - 1] << endl;
                sp--;
                break;
            case RET://结束被调用过程，返回调用点，退栈并将返回值存入退栈后的栈顶
                int rv;//Return value记录返回值
                rv = stack[sp - 1];
                sp = bp;
                bp = stack[sp];
                ip = stack[sp + 1];
                stack[sp] = rv;
                sp++;
                stack.resize(sp);
                break;
        }
    } while (ip != 0);
    fa2.close();
}

int gen(fct x, int y, int z) {
    if (cx >= cxMax) {
        cout << "Program too long";
        return -1;
    }
    fa << fctToStr(x) << " " << y << " " << z << endl;
    cx++;
    return 0;
}

int base(int l, vector<int> &s, int bp) {
    int b;
    b = bp;
    while (l > 0) {
        b = s[b];
        l--;
    }
    return b;
}
